Workflow instance was too large to persist
Table of Contents
Spotkałeś się kiedyś z tym problemem? Workflow działa poprawnie i nagle, bez zrozumiałego powodu, przechodzi w stan „suspended” (zawieszony)? Wówczas, gdy najedziesz na ikonkę „i” obok statusu, by uzyskać więcej informacji, pokaże się komunikat, iż „The workflow instance was too large to persist”? Ja ostatnio zacząłem obserwować takie zachowania. Poniżej opisuję wyniki mojej analizy i rekomendacje, jak tego uniknąć lub rozwiązać ten problem.
[tds_note] Opisywane rozwiązania i scenariusz pojawia się błędu są właściwe dla rozwiązania bazującego na formularzu InfoPath zapisywanym do biblioteki formularzy. Nie dotyczy to sytuacji, gdy formularz InfoPath działa jako formularz elementu listy lub biblioteki (choć być może naprowadzi na rozwiązanie 🙂 ).[/tds_note]
Problem zaczął się pojawiać podczas pracy z Nintex dla Office 365. Klient myślał, że skoro workflow się zawiesza, to jest to problem wprost związany z wielkością jego przepływu pracy (miał wówczas ok. 95 akcji). Jednak na początku był również formularz InfoPath, który był zapisywany jako plik do biblioteki formularzy. Sam InfoPath był całkiem duży, zbudowany z 3 stron i wielu pól, które dodatkowo były powtarzalne.
Workflow cały czas się zawieszał twierdząc, że jego instancja „jest za duża, by trwać” (too large to persist), jako przyczynę podając poniższe powody:
RequestorId: 86e24769-e969-3395-0000-000000000000. Details: The workflow instance was too large to persist (over 9801 kilobytes uncompressed, over 6830 kilobytes compressed). The maximum persistable workflow instance size is 15360 kilobytes uncompressed and 5120 kilobytes compressed.
Zaintrygował mnie fakt, że wielkość samego, nieskompresowanego workflowu, wynosiła ok. 1.2MB (źródło: http://help.nintex.com/en-US/O365/o365/O365WorkFlow/BestPractices/BP-Determinefilesize.htm), a zatem do ustalonego limitu, 5MB było jeszcze sporo przestrzeni. Sam formularz, wraz z załącznikami, również nie przekraczał 1MB, zatem workflow teoretycznie miał do dyspozycji ponad 2.5MB. Z drugiej strony nie bardzo rozumiałem, dlaczego InfoPath miałby być wliczony w wielkość przepływu… Cóż, czytaj dalej 🙂
Moje śledztwo
Mimo wszystko zacząłem od tego, co wychodzi mi najlepiej – zoptymalizowałem przepływ pracy i podzieliłem go na 4 mniejsze (jest to jedna z rekomendacji Microsoft – dzielić duże przepływy na mniejsze, wywołujące się wzajemnie). Dzięki temu zabiegowi, rozmiar głównego przepływu, zawierającego proces zatwierdzania, zmalał do 430KB. Mimo to jednak, gdy do formularza załączałem pliki, powodując wzrost jego wielkości do ok. 3.6MB, proces się zawieszał.
Spróbowałem także inaczej – stworzyłem mały workflow (15 akcji, ok. 100KB rozmiaru), który pracował z biblioteką formularzy, ale nie przetwarzał samego formularza InfoPath, Ku memu zaskoczeniu, workflow nie tylko zaczął działać i zakończył przetwarzanie w bardzo krótkim czasie (kilka sekund, podczas gdy najkrótszy z 4 potrzebował ok. 2 minut), to jeszcze się nie zawiesił…
To mi dało do myślenia…
Na początek – formularz InfoPath. Na pewno wiesz, że formularz InfoPath zapisywany do biblioteki formularzy, jako plik, jest po prostu czystym XMLem. Wszystko, co widzisz na formularzu jest zapisane w strukturze XML pod spodem. Wszystkie dodane obrazki, układ, kolory, formatowanie – ma swoje definicje w XML.
Kiedy dodasz pole „File”, umożliwiające załączanie plików do formularza, gdy użytkownik użyje je w celu wgrania dokumentu, ten zostanie w locie zdekodowany na ciąg Base64 i… wiesz co? Tak! Zostanie zapisany bezpośrednio do XMLa 🙂
[tds_note] W SharePoint Online limit dla wielkości pojedynczego formularza InfoPath, wraz z załącznikami wynosi 5MB i nie można tego zmienić.[/tds_note]
Następnie – workflow. Zauważyłem, że tym, co głównie odróżnia mój testowy workflow, od tych produkcyjnych (ok, zrobiłem to celowo :)) były akcje odczytu i zapisu do XML (Query i Update XML), które pracowały bezpośrednio na pliku InfoPath. Mój pierwszy pomysł był taki, że aby móc przetwarzać formularz, Workflow Manager musi wgrać całą jego zawartość do instancji przepływu pracy.
Następnie, gdy zawartość jest wgrana, z reguły musi odnaleźć wskazany węzeł w strukturze, używając zapytania xpath i wykonać na nim wskazaną operację. Gdyby to był prosty XML, zapewne operacja ta przebiegła by szybko i sprawnie, jednak w przypadku rozbudowanych XMLi, wypełnionych dodatkowo ciągami Base64, które tworzą pokaźne zestawy danych do przetworzenia, ten czas jest znacznie dłuższy. Podejrzewam, że moment, w którym Workflow Manager serializuje XML i yapisuje go do bazy danych, jest tym momentem, w którym się orientuje, że instancja workflowu właśnie przekroczyła ustalone progi (sugestie). Nie mogę powiedzieć nic na pewno, to wciąż są tylko domysły, ale mnie ta teoria przekonuje, wyjaśniając dlaczego 1MB workflow i 1MB formularz InfoPath podczas trwania przepływu pracy przekraczają ustalony, 5MB próg.
Wnioski
Wygląda na to, że zupełnie bez znaczenia będzie, co jeszcze zrobię z przepływem pracy Nintex, jak bardzo go dalej będę optymalizować nie tu leży problem. Moim zdaniem źródłem problemu jest sam Workflow Manager, który obsługuje przetwarzanie XMLa. I tak długo, jak będzie używany formularz InfoPath, workflow najpewniej nadal będzie się zawieszać. Napisz w komentarzu, jeśli masz inne przypuszczenia 🙂
Jak to rozwiązać?
- W SharePoint on-premise, gdzie jesteś Panem, możesz zmieniać domyślne progi i limity. Żeby zwiększyć dopuszczalną wielkość instancji workflowu, zwyczajnie uruchom poniższy skrypt PowerShell:
Set-WFServiceConfiguration -ServiceUri http://workflowmanagerurl:12291/ -Name “WorkflowServiceMaxInstanceSizeKB” -Value NEW_LIMIT_IN_BYTES
[tds_info] Po ustawieniu nowego limitu zresetuj usługę Windows ‘Workflow Manager Backend’ dzięki czemu zmiany zostaną uwzględnione.[/tds_info]
- W obu przypadkach, tj. SharePoint Online i SharePoint on-premise, warto zmapować pola z InfoPath na kolumny w SharePoint. Robi się to poprzez przejście do zakładki „Plik –> Publikacja –> Serwer SharePoint”. Następnie wybierz dodaj pole z pośród posiadanych na formularzu i w ustawieniach mapowania zaznacz checkbox „Pozwalaj użytkownikom na edytowanie danych w tym polu…”:
W ten sposób, gdy wartość w kolumnie zostanie zmodyfikowana przez przepływ Nintex Workflow, wartość w formularzu InfoPath zmieni się również, jednak do osiągnięcia tego nie będzie trzeba używać żadnej akcji spośród Query lub Update XML. W mojej ocenie tak powinno się robić z nieomal każdym polem, które ma być przetwarzane w trakcie trwania procesu.
Co istotne, takiego związania nie można zrobić dla wszystkich rodzajów pól w InfoPath. Jedynie dla prostych typów. Żadne z „kontenerów”, „list” (Containers, Lists) oraz danych w nich stworzonych nie da się powiązać. Nie jest to także możliwe dla pól „Osoba/ Grupa” (Person/Group). Także ta koncepcja posiada swoje ograniczenia, ale wciąż jest istotna.
- W obu przypadkach, tj. SharePoint Online i SharePoint on-premise, jeśli posiadasz licencję na Nintex Forms, naprawdę – użyj tego rozwiązania. Największą jego zaletą jest fakt, że nie przechowuje żadnego XMLa w swojej strukturze, wszystkie dane są zapisywane bezpośrednio do kolumn listy. Np. każda sekcja powtarzalna (repeating section) jest zapisywana jako pojedyncza kolumna, zatem przetwarzanie takich XMLi jest dużo prostsze. Dane „Form Data” (NFFormData w Nintex dla Office 365) – czyli dane z każdego pola w formularzu, zapisane do struktury XML, również są zapisywane do bazy danych Nintex, zatem także nie istnieje konieczność ich wgrywania do instancji przepływu pracy i narażania go na błędy.
A jakie jest Twoje doświadczenie? Proszę, podziel się swoimi wnioskami i spostrzeżeniami w komentarzu.